unit SortThds;

interface

uses
  Classes, Graphics, ExtCtrls, UMono, UMonoIntf, UVarMono, Variants, windows;

type

{ TSortThread }

  TIntSortArray = array of integer;
  PIntSortArray = ^TIntSortArray;


  TSortThread = class(TThread)
  private
    FBox: TPaintBox;
    FSortArray: PIntSortArray;
    FSize: Integer;
    FA, FB, FI, FJ: Integer;
    FDomainObj: TAppDomain;
    FMonoClass: PMonoClass;
    Fmsg: string;
    procedure DoVisualSwap;
    procedure DoShowMessage;
  protected
    procedure Execute; override;
    procedure Sort(var A: TIntSortArray); virtual;
  public
    procedure BeforeDestruction; override;
    property Terminated;
    procedure VisualSwap(A, B, I, J: Integer);
    procedure ShowMessage(text: string);
    constructor Create(Box: TPaintBox; var SortArray: TIntSortArray; aFileName: string; aNameSpace, aClassName: string);

  end;



procedure PaintLine(Canvas: TCanvas; I, Len: Integer);

implementation
uses Dialogs;

procedure PaintLine(Canvas: TCanvas; I, Len: Integer);
begin
  Canvas.PolyLine([Point(0, I * 2 + 1), Point(Len, I * 2 + 1)]);
end;

{ TSortThread }

procedure TSortThread.BeforeDestruction;
begin
  inherited;
  FDomainObj.Free;
end;

constructor TSortThread.Create(Box: TPaintBox; var SortArray: TIntSortArray;
  aFileName: string; aNameSpace, aClassName: string);
begin
  FBox := Box;
  FSortArray := @SortArray;
  FSize := Length(SortArray);
  FreeOnTerminate := True;
  FDomainObj := TAppDomain.Create(aClassName+'dom', MonoJit);
  FDomainObj.LoadMainAssembly(aFileName);
  FMonoClass := MonoJit.FindMonoClass(aNameSpace, aClassName, FDomainObj.MainImage);
  inherited Create(False);
end;

{ Since DoVisualSwap uses a VCL component (i.e., the TPaintBox) it should never
  be called directly by this thread.  DoVisualSwap should be called by passing
  it to the Synchronize method which causes DoVisualSwap to be executed by the
  main VCL thread, avoiding multi-thread conflicts. See VisualSwap for an
  example of calling Synchronize. }

procedure TSortThread.DoShowMessage;
begin
  Dialogs.ShowMessage(Fmsg);
end;

procedure TSortThread.DoVisualSwap;
begin
  with FBox do
  begin
    Canvas.Pen.Color := clBtnFace;
    PaintLine(Canvas, FI, FA);
    PaintLine(Canvas, FJ, FB);
    Canvas.Pen.Color := clRed;
    PaintLine(Canvas, FI, FB);
    PaintLine(Canvas, FJ, FA);
  end;
end;

{ VisusalSwap is a wrapper on DoVisualSwap making it easier to use.  The
  parameters are copied to instance variables so they are accessable
  by the main VCL thread when it executes DoVisualSwap }

procedure TSortThread.VisualSwap(A, B, I, J: Integer);
begin
  FA := A;
  FB := B;
  FI := I;
  FJ := J;
  Synchronize(DoVisualSwap);
end;

{ The Execute method is called when the thread starts }

procedure TSortThread.Execute;
begin
  NameThreadForDebugging(AnsiString(ClassName));
  mono_thread_attach(FDomainObj.MonoDomain);
  Sort(FSortArray^);
end;

procedure TSortThread.ShowMessage(text: string);
begin
  Fmsg := text;
  Synchronize(DoShowMessage);
end;

procedure TSortThread.Sort(var A: TIntSortArray);
var
  vObj: variant;
  vArray: variant;
begin
  vObj := VarMonoCreate(FMonoClass, 'Mono4Delphi.ITSortThread', [self], FDomainObj.MonoDomain);
  vArray := a;
  vObj.Sort(vArray);
  a := vArray;
end;


end.
